//
// Created by F1997 on 2024/12/24.
//

#include "IniReader.h"

namespace ntp {

// 读取配置文件
    bool IniReader::ReadConfig(const std::string& filename)
    {
        settings_.clear();
        std::ifstream infile(filename.c_str()); // infile 为定义的输入流，filename为输入文件名
        // 等价于
        std::ifstream file;
        file.open(filename.c_str());

        if (!infile.is_open()) {
            return false; // 文件打开失败
        }

        std::string line, key, value, section; // 行，配置项，配置值，配置段
        ss_map k_v;
        std::map<std::string, ss_map>::iterator it; // 按配置段分类的配置map
        while (getline(infile, line)) {
            if (AnalyseLine(line, section, key, value)) {
                it = settings_.find(section);
                if (it != settings_.end()) {
                    k_v[key] = value;
                    it->second = k_v;
                }
                else {
                    k_v.clear();
                    settings_.insert(std::make_pair(section, k_v));
                }
            }
            key.clear();
            value.clear();
        }
        infile.close();
        return true;
    }

// 从配置map中读取配置项
    std::string IniReader::ReadString(const char* section, const char* item, const char* default_value)
    {
        ss_map k_v;
        ss_map::iterator it_item;
        std::map<std::string, ss_map>::iterator it;
        it = settings_.find(std::string(section));
        if (it == settings_.end()) {
            return std::string(default_value);
        }

        k_v = it->second;
        it_item = k_v.find(std::string(item));
        if (it_item == k_v.end()) {
            return std::string(default_value);
        }

        size_t hc = it_item->second.find('\r');
        if (hc != std::string::npos) {
            return it_item->second.substr(0,hc);
        }
        else {
            return it_item->second;
        }
    }


    int IniReader::ReadInt(const char* section, const char* item, const int& default_value)
    {
        ss_map k_v;
        ss_map::iterator it_item;
        std::map<std::string, ss_map>::iterator it;
        it = settings_.find(std::string(section));
        if (it == settings_.end()) {
            return default_value;
        }

        k_v = it->second;
        it_item = k_v.find(std::string(item));
        if (it_item == k_v.end()) {
            return default_value;
        }

        return atoi(it_item->second.c_str());
    }


    double IniReader::ReadFloat(const char* section, const char* item, const float& default_value)
    {
        ss_map k_v;
        ss_map::iterator it_item;
        std::map<std::string, ss_map>::iterator it;
        it = settings_.find(std::string(section));
        if (it == settings_.end()) {
            return default_value;
        }

        k_v = it->second;
        it_item = k_v.find(std::string(item));
        if (it_item == k_v.end()) {
            return default_value;
        }

        return atof(it_item->second.c_str());
    }

// 过滤左右空格
    void IniReader::Trim(std::string & str)
    {
        if (str.empty()) {
            return;
        }

        str.erase(0, str.find_first_not_of(" "));
        str.erase(str.find_last_not_of(" ") + 1);
    }

// 解析配置文件中的行数据到对应变量，配置文件用=分割配置项和值
    bool IniReader::AnalyseLine(const std::string& line, std::string& section, std::string& key, std::string& value)
    {
        if (line.empty()) {
            return false;
        }

        size_t start_pos = 0, end_pos = line.size() - 1, pos, s_startpos, s_endpos;
        if ((pos = line.find("#")) == 0) { // 行首加#，则本行被注释，不解析
            if (0 == pos) {
                return false;
            }
            end_pos = pos - 1;
        }

        // []用来区分配置段，如[config]
        if (((s_startpos = line.find("[")) != std::string::npos) && ((s_endpos = line.find("]"))) != std::string::npos) {
            section = line.substr(s_startpos + 1, s_endpos - 1);
            return true;
        }

        std::string new_line = line.substr(start_pos, start_pos + 1 - end_pos);
        if ((pos = new_line.find('=')) == std::string::npos) { // std::string::npos = string类的静态成员变量，它表示一个无效的或者不存在的字符串位置或索引
            return false; // 该行没有"="，则为无效配置项
        }

        key = new_line.substr(0, pos);
        value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1));

        Trim(key);
        if (key.empty()) {
            return false;
        }

        Trim(value);
        if (value.empty()) {
            return false;
        }

        return true;
    }

    // 获取相似配置的名称列表
    std::vector<std::string> IniReader::GetSimilarConfigNames(const std::string& section) {
        std::vector<std::string> similar_names;
        settings_.find(section);
        // 遍历配置map，找到相似的配置名称
        for (const auto& entry : settings_) {
            if (entry.first.find(section) != std::string::npos) { // std::string::npos，表示在字符串中未找到匹配的位置
                similar_names.push_back(entry.first);
            }
        }
        return similar_names;
    }

} // ntp